﻿using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using UnityEditor;
using UnityEngine;
using System.Text;
using System.Diagnostics;
using UnityModule;
using System.Runtime.InteropServices;
using System;
using Debug = UnityEngine.Debug;

namespace EditorModule
{
    public static class BuildTool
    {
        [MenuItem("Build/UI代码生成", false, 0)]
        public static void PrefabUICodeBuilder()
        {
            EditorWindow.GetWindow<PrefabUICodeBuilder>(false);
        }
        [MenuItem("Build/出包+资源编译", false, 1)]
        public static void BuildToolEditor()
        {
            EditorWindow.GetWindow<BuildToolEditor>(false);
        }
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    public class OpenFileName
    {
        public int structSize = 0;
        public IntPtr dlgOwner = IntPtr.Zero;
        public IntPtr instance = IntPtr.Zero;
        public String filter = null;
        public String customFilter = null;
        public int maxCustFilter = 0;
        public int filterIndex = 0;
        public String file = null;
        public int maxFile = 0;
        public String fileTitle = null;
        public int maxFileTitle = 0;
        public String initialDir = null;
        public String title = null;
        public int flags = 0;
        public short fileOffset = 0;
        public short fileExtension = 0;
        public String defExt = null;
        public IntPtr custData = IntPtr.Zero;
        public IntPtr hook = IntPtr.Zero;
        public String templateName = null;
        public IntPtr reservedPtr = IntPtr.Zero;
        public int reservedInt = 0;
        public int flagsEx = 0;
    }
    public class LocalDialog
    {
        //链接指定系统函数       打开文件对话框
        [DllImport("Comdlg32.dll", SetLastError = true, ThrowOnUnmappableChar = true, CharSet = CharSet.Auto)]
        public static extern bool GetOpenFileName([In, Out] OpenFileName ofn);
        public static bool GetOFN([In, Out] OpenFileName ofn)
        {
            return GetOpenFileName(ofn);
        }

        //链接指定系统函数        另存为对话框
        [DllImport("Comdlg32.dll", SetLastError = true, ThrowOnUnmappableChar = true, CharSet = CharSet.Auto)]
        public static extern bool GetSaveFileName([In, Out] OpenFileName ofn);
        public static bool GetSFN([In, Out] OpenFileName ofn)
        {
            return GetSaveFileName(ofn);
        }
    }

    public partial class BuildToolEditor : EditorWindow
    {
        private const int c_layoutW = 480;
        private const int c_layoutH = 400;

        private Rect m_rect0 = new Rect(0, 0, c_layoutW, c_layoutH);
        private Rect m_rect1 = new Rect(c_layoutW, 0, c_layoutW, c_layoutH);
        private Rect m_rect2 = new Rect(0, c_layoutH, c_layoutW, c_layoutH * 2f);
        //private Rect m_rect3 = new Rect(c_layoutW, c_layoutH, c_layoutW, c_layoutH * 2f);
        //private Rect m_rect4 = new Rect(0, c_layoutH * 2f, c_layoutW, c_layoutH);
        //private Rect m_rect5 = new Rect(c_layoutW, c_layoutH * 2f, c_layoutW, c_layoutH);

        private Vector2 m_minSize = new Vector2((c_layoutW) * 2, (c_layoutH));

        private bool m_JustEnabled;
        private Vector2 m_ReleaseNoteScrollPos = Vector2.zero;
        private GUIStyle m_StyleBox;

        bool m_setABName = true;
        //资源相关
        private const string DirectoryRoot = "资源编辑器/AssertBundle/";
        private const string ITEM_BUILD_BUNDLE = "编译bundle";
        private const string ITEM_DELETE_BUNDLE = "删除编译目录bundle";
        private const string ITEM_DELETE_SA_BUNDLE = "删除StreamingAssets目录bundle";
        private const string COPY_TO_STREAMINGASSETS = "拷贝到StreamingAssets";
        //--资源相关end

        private const string USE_LOG = "USE_LOG";
        protected void OnEnable()
        {
            m_JustEnabled = true;
        }
        public void Initialize()
        {
            titleContent.text = "出包+资源编译工具";
            minSize = m_minSize;
            SetupGUIStyle();
        }

        void SetupGUIStyle()
        {
            m_StyleBox = new GUIStyle(GUI.skin.box);
            m_StyleBox.fontSize = 28;
            m_StyleBox.fontStyle = FontStyle.Bold;
        }


        private void ResourcesBuildAbout()
        {

            GUILayout.BeginArea(m_rect0, m_StyleBox);
            GUILayout.Label("资源编译工具");
            GUILayout.Space(5);

            if (GUILayout.Button(new GUIContent("删除编译目录bundle", "工程目录下的bundle"), new GUILayoutOption[] { GUILayout.MaxWidth(c_layoutW) }))
            {
                BuildBundles.DeleteBuildDirectoryFiles();
            }
            if (GUILayout.Button(new GUIContent("删除StreamingAssets目录bundle", "StreamingAssets目录下的bundle!"), new GUILayoutOption[] { GUILayout.MaxWidth(c_layoutW) }))
            {
                BuildBundles.DeleteSABundles();
            }
            if (GUILayout.Button(new GUIContent("CopyLua", "发布才用"), new GUILayoutOption[] { GUILayout.MaxWidth(c_layoutW) }))
            {
                SetBundles.CopyLua();
            }
            if (GUILayout.Button(new GUIContent("编译bundle", "编译当前平台bundle!不支持断点续传"), new GUILayoutOption[] { GUILayout.MaxWidth(c_layoutW) }))
            {
                BuildBundles.Build();
            }
            if (GUILayout.Button(new GUIContent("发布前处理30058", "发布前请点击！ios需要拷贝，android,pc需要删除"), new GUILayoutOption[] { GUILayout.MaxWidth(c_layoutW) }))
            {
                BuildBundles.Copy30058();
            }
            
            GUILayout.BeginHorizontal();
            m_setABName = GUILayout.Toggle(m_setABName, "设置所有abName");
            if (GUILayout.Button(new GUIContent("一键发布", "一键发布"), new GUILayoutOption[] { GUILayout.MaxWidth(c_layoutW) }))
            {
                // Debug.LogError(m_setABName);
                SetBundles.CopyLua();
                BuildBundles.Build(m_setABName);
            }
            GUILayout.EndHorizontal();
            if (GUILayout.Button(new GUIContent("拷贝到StreamingAssets", "拷贝所有资源到StreamingAssets"), new GUILayoutOption[] { GUILayout.MaxWidth(c_layoutW) }))
            {
                BuildBundles.CopyToStreamingAssets(BuildBundles.emAssetType.Full);
            }

            if (GUILayout.Button(new GUIContent("设置bundle名称", "设置bundle名称!"), new GUILayoutOption[] { GUILayout.MaxWidth(c_layoutW) }))
            {
                SetBundles.SetAssetBundleNames();
            }

            if (GUILayout.Button(new GUIContent("发布测试", "..."), new GUILayoutOption[] { GUILayout.MaxWidth(c_layoutW) }))
            {
                if (EditorPlatform.GetPlatformName() != "windows")
                {
                    EditorUtility.DisplayDialog("Hint", "当前平台不是windows", "Yes");
                    return;
                }
                BuildBundles.Build();
                //copy res
                string currDir = Directory.GetCurrentDirectory();
                string pb_path = Application.dataPath.Replace("Assets", string.Empty) + "\\Proto\\";

                Directory.SetCurrentDirectory(pb_path);
                System.Diagnostics.Process pro = System.Diagnostics.Process.Start(pb_path + "______copy_res.bat");
                pro.WaitForExit();
                Directory.SetCurrentDirectory(currDir);
            }

            if (GUILayout.Button(new GUIContent("发布远程资源", "..."), new GUILayoutOption[] { GUILayout.MaxWidth(c_layoutW) }))
            {
                string plat = EditorPlatform.GetPlatformName();
                if (EditorUtility.DisplayDialog("Hint", $"确定发布远程资源{plat}", "Yes","No"))
                {
                    BuildServerRes($"______copy_res_{plat}.bat");
                }
            }

            if (GUILayout.Button(new GUIContent("生成Json", "..."), new GUILayoutOption[] { GUILayout.MaxWidth(c_layoutW) }))
            {
                OpenFileName openFileName = new OpenFileName();
                openFileName.structSize = Marshal.SizeOf(openFileName);
                openFileName.filter = "Bin文件(*.bin)\0*.bin";
                openFileName.file = new string(new char[256]);
                openFileName.maxFile = openFileName.file.Length;
                openFileName.fileTitle = new string(new char[64]);
                openFileName.maxFileTitle = openFileName.fileTitle.Length;
                openFileName.initialDir = Application.streamingAssetsPath.Replace('/', '\\');//默认路径
                openFileName.title = "窗口标题";
                openFileName.flags = 0x00080000 | 0x00001000 | 0x00000800 | 0x00000008;

                if (LocalDialog.GetSaveFileName(openFileName))
                {
                    //Debug.Log(openFileName.file);
                    //Debug.Log(openFileName.fileTitle);

                    int index = openFileName.file.LastIndexOf('\\');
                    string path = openFileName.file.Substring(0, index + 1);

                    byte[] data = File.ReadAllBytes(openFileName.file);
                    Dictionary<string, AssetBundleInfoV2> bundleBinInfo = null;
                    using (MemoryStream ms = new MemoryStream(data))
                    {
                        BinaryFormatter bf = new BinaryFormatter();
                        bundleBinInfo = bf.Deserialize(ms) as Dictionary<string, AssetBundleInfoV2>;
                    }
                    BuildBundles.SaveServerFile(path, bundleBinInfo);

                    Debug.Log($"{openFileName.file} 生成Project.json OK");
                }
            }

            if (GUILayout.Button(new GUIContent("生成SpineJson", "..."), new GUILayoutOption[] { GUILayout.MaxWidth(c_layoutW) }))
            {
                    UpSpine.Upgrade();
            }
            //if (GUILayout.Button(new GUIContent("检查-->bundle名称", "检查bundle名称!"), new GUILayoutOption[] { GUILayout.MaxWidth(c_layoutW) }))
            //{
            //    SetBundles.CheckBundles();
            //}
            //if (GUILayout.Button(new GUIContent("清除-->bundle名称", "清除bundle名称!"), new GUILayoutOption[] { GUILayout.MaxWidth(c_layoutW) }))
            //{
            //    string[] names = AssetDatabase.GetAllAssetBundleNames();
            //    if (names != null)
            //    {
            //        foreach (string n in names)
            //        {
            //            AssetDatabase.RemoveAssetBundleName(n, true);
            //        }
            //    }
            //}
            GUILayout.EndArea();
        }


        private void BuildServerRes(string bat)
        {
            SetBundles.CopyLua();
            BuildBundles.Build();
            //copy res
            string currDir = Directory.GetCurrentDirectory();
            string pb_path = @"D:\_Server\";

            Directory.SetCurrentDirectory(pb_path);
            System.Diagnostics.Process pro = System.Diagnostics.Process.Start(pb_path + bat);
            pro.WaitForExit();
            Directory.SetCurrentDirectory(currDir);
        }

        BuildBundles.emAssetType AssetType = BuildBundles.emAssetType.None;
        //bool ZipRes = false;
        //bool UnionBundle = false;
        private void OneKeyRelease()
        {
            GUILayout.BeginArea(m_rect2, m_StyleBox);
            GUILayout.Label("一键发布");
            GUILayout.Space(5);

            GUILayout.BeginHorizontal();
            if (GUILayout.Toggle(AssetType == BuildBundles.emAssetType.None, new GUIContent("【无资源】", ""), EditorStyles.radioButton))
            {
                AssetType = BuildBundles.emAssetType.None;
            }
            if (GUILayout.Toggle(AssetType == BuildBundles.emAssetType.Custome, new GUIContent("【小包】", ""), EditorStyles.radioButton))
            {
                AssetType = BuildBundles.emAssetType.Custome;
            }
            if (GUILayout.Toggle(AssetType == BuildBundles.emAssetType.Full, new GUIContent("【完整包】", ""), EditorStyles.radioButton))
            {
                AssetType = BuildBundles.emAssetType.Full;
            }

            GUILayout.EndArea();
        }
        static string[] GetBuildScenes()
        {
            List<string> names = new List<string>();
            foreach (EditorBuildSettingsScene e in EditorBuildSettings.scenes)
            {
                if (e == null)
                    continue;
                if (e.enabled)
                    names.Add(e.path);
            }
            return names.ToArray();
        }
        private void NormalBuildAbout()
        {
            GUILayout.BeginArea(m_rect1, m_StyleBox);
            GUILayout.Label("其它预编译符工具");
            GUILayout.Space(5);

            if (GUILayout.Button(new GUIContent("带Log", "预编译: +USE_LOG"), new GUILayoutOption[] { GUILayout.MaxWidth(c_layoutW) }))
            {
                ScriptingDefine.Define(USE_LOG);
            }
            if (GUILayout.Button(new GUIContent("不带Log", "预编译: -USE_LOG"), new GUILayoutOption[] { GUILayout.MaxWidth(c_layoutW) }))
            {
                ScriptingDefine.Undefine(USE_LOG);
            }

            if (GUILayout.Button(new GUIContent("无预编译", "无预编译"), new GUILayoutOption[] { GUILayout.MaxWidth(c_layoutW) }))
            {
                string strDefine = "";
                ScriptingDefine.PresetPlatformDefine(ref strDefine, new string[] { }, true);
                ScriptingDefine.SetAll(strDefine);
            }

            GUILayout.EndArea();
        }



        private void OnGUI()
        {
            if (m_JustEnabled)
            {
                Initialize();
                m_JustEnabled = false;
            }

            using (var scrollScope = new EditorGUILayout.ScrollViewScope(m_ReleaseNoteScrollPos, GUI.skin.scrollView))
            {
                m_ReleaseNoteScrollPos = scrollScope.scrollPosition;

                ResourcesBuildAbout();
                //OneKeyRelease();
                NormalBuildAbout();
            }
            EditorGUILayout.HelpBox("当前预编译:" + PlayerSettings.GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup), MessageType.Info);
        }


        private string responseFormat(string json)
        {
            StringBuilder jsonStr = new StringBuilder();
            int level = 0;
            for (int index = 0, len = json.Length; index < len; index++)
            {//将字符串中的字符逐个按行输出
             //获取s中的每个字符
                char c = json[index];
                //level大于0并且jsonForMatStr中的最后一个字符为\n,jsonForMatStr加入\t
                if (level > 0 && '\n' == jsonStr[jsonStr.Length - 1])
                {
                    jsonStr.Append(getLevelStr(level));
                }
                //遇到"{"和"["要增加空格和换行，遇到"}"和"]"要减少空格，遇到","要换行
                switch (c)
                {
                    case '{':
                    case '[':
                        jsonStr.Append(c + "\n");
                        level++;
                        break;
                    case ',':
                        jsonStr.Append(c + "\n");
                        break;
                    case '}':
                    case ']':
                        jsonStr.Append("\n");
                        level--;
                        jsonStr.Append(getLevelStr(level));
                        jsonStr.Append(c);
                        break;
                    default:
                        jsonStr.Append(c);
                        break;
                }
            }
            return jsonStr.ToString();
        }

        private string getLevelStr(int level)
        {
            StringBuilder levelStr = new StringBuilder();
            for (int levelI = 0; levelI < level; levelI++)
            {
                levelStr.Append("\t");
            }
            return levelStr.ToString();
        }
    }


    public class asmdefClass
    {
        public string name;
        public List<string> references;
        public List<string> optionalUnityReferences;
        public List<string> includePlatforms;
        public List<string> excludePlatforms;
        public bool allowUnsafeCode;
        public bool overrideReferences;
        public List<string> precompiledReferences;
        public bool autoReferenced;
        public List<string> defineConstraints;
        public List<string> versionDefines;
    }


}
